/*
 * Copyright (c) 2021-2025 dresden elektronik ingenieurtechnik gmbh.
 * All rights reserved.
 *
 * The software in this package is published under the terms of the BSD
 * style license a copy of which has been included with this distribution in
 * the LICENSE.txt file.
 *
 */

#ifndef BUTTON_MAPS_H
#define BUTTON_MAPS_H

#include <cstdint>
#include <vector>

using ProductIdHash = std::uint32_t;

/*! Reference to a button map for quick lookup and leightweight embedding. */
struct ButtonMapRef
{
    uint32_t hash = 0; //! hash of button map name
    uint32_t index = UINT32_MAX; //! index into ButtonMap vector
};

/*! Meta data about buttons, not used by the plugin but exposed via REST API. */
struct ButtonMeta
{
    struct Button
    {
        uint32_t nameAtomeIndex;
        int button;
    };

    std::vector<ButtonMeta::Button> buttons;
    ButtonMapRef buttonMapRef{};
};

/*! Mapping between a product and a buttom map.
 */
struct ButtonProduct
{
    ButtonMapRef buttonMapRef{};
    ProductIdHash productHash = 0; //! hash of modelid or manufacturer name generated by \c productHash(Resource*)
};

struct ButtonCluster
{
    uint32_t nameAtomIndex;
    uint32_t clusterId;
};

struct ButtonClusterCommand
{
    uint32_t clusterNameAtomIndex;
    uint32_t commandNameAtomIndex;
    uint32_t commandId;
};

struct ButtonMap
{
    struct Item
    {
        uint8_t mode;
        uint8_t endpoint;
        uint8_t zclCommandId;
        uint8_t pad0;
        uint16_t clusterId;
        uint16_t zclParam0;
        int button;
        uint32_t nameAtomIndex;
    };
    std::vector<ButtonMap::Item> buttons;
    ButtonMapRef buttonMapRef{};
};

ButtonMapRef BM_ButtonMapRefForHash(uint32_t buttonMapNameHash, const std::vector<ButtonMap> &buttonMaps);
const ButtonMap *BM_ButtonMapForRef(ButtonMapRef ref, const std::vector<ButtonMap> &buttonMaps);
const ButtonMap *BM_ButtonMapForProduct(ProductIdHash productHash, const std::vector<ButtonMap> &buttonMaps, const std::vector<ButtonProduct> &buttonProductMap);

inline bool isValid(ButtonMapRef a) { return a.hash != 0 && a.index != UINT32_MAX; }
inline bool operator==(ButtonMapRef a, ButtonMapRef b) { return a.hash == b.hash && a.index == b.index; }
inline bool operator!=(ButtonMapRef a, ButtonMapRef b) { return !(a == b); }

#endif // BUTTON_MAPS_H
